package com.yuyou.fn.platform.service.impl;

import com.github.wens.mybatisplus.examples.Example;
import com.yuyou.fn.platform.entity.SysRoleResource;
import com.yuyou.fn.platform.entity.SysUserRole;
import com.yuyou.fn.platform.service.ISysRoleResourceService;
import com.yuyou.fn.platform.service.ISysUserRoleService;
import com.yuyou.fn.common.util.BeanUtils;
import com.yuyou.fn.platform.vo.SysResourceVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.yuyou.fn.platform.mapper.SysResourceMapper;
import com.yuyou.fn.platform.entity.SysResource;
import com.yuyou.fn.platform.service.ISysResourceService;
import com.github.wens.framework.service.impl.SuperServiceImpl;

import javax.annotation.Resource;
import java.util.*;

/**
 *
 * SysResource 表数据服务层接口实现类
 *
 */
@Service
public class SysResourceServiceImpl extends SuperServiceImpl<SysResourceMapper, SysResource,Long> implements ISysResourceService {

    private static final Logger logger = LoggerFactory.getLogger(SysResourceServiceImpl.class) ;

    @Resource
    private ISysRoleResourceService sysRoleResourceService;

    @Resource
    private ISysUserRoleService sysUserRoleService ;

    @Cacheable(value = "CacheOfResource",key = "#userId")
    @Override
    public List<SysResourceVo> findResourceByUserIdFromCache(Long userId) {

        List<SysUserRole> sysUserRoleList = sysUserRoleService.findRoleByUserId(userId);

        List<Long> roleIds = BeanUtils.toList(sysUserRoleList , "roleId");

        if(roleIds.isEmpty()){
            return Collections.EMPTY_LIST ;
        }

        List<SysRoleResource> sysRoleResourceList = sysRoleResourceService.findRoleResourceByRoleIds(roleIds);

        Map<Long,SysRoleResource> sysRoleResourceMap = BeanUtils.toMap(sysRoleResourceList,"resourceId");
        List<SysResourceVo> resourceList = findAllResource();
        List<SysResourceVo> userResourceList = copyUserResource(sysRoleResourceMap, resourceList );;
        return userResourceList;
    }


    private List<SysResourceVo> copyUserResource(Map<Long, SysRoleResource> sysRoleResourceMap, List<SysResourceVo> resourceList) {

        List<SysResourceVo> newResourceList  = new ArrayList<>(resourceList.size()) ;

        for(SysResourceVo resourceVo : resourceList ){
            if(sysRoleResourceMap.containsKey(resourceVo.getResourceId())){
                newResourceList.add(resourceVo);
                if(resourceVo.getChildren() != null  ){
                    resourceVo.setChildren( copyUserResource(sysRoleResourceMap, resourceVo.getChildren()) ) ;
                }
            }
        }
        return newResourceList ;
    }

    @Override
    public List<SysResourceVo> findAllResource() {
        Example<SysResource> example = SysResource.createExample();
        List<SysResource> allResourceList = findListByExample(example);
        Map<Long,SysResource> allResourceMap =  BeanUtils.toMap(allResourceList, "resourceId");
        return toResourceVo( allResourceList , allResourceMap, 0L);
    }

    private List<SysResourceVo> toResourceVo(List<SysResource> allResourceList , Map<Long, SysResource> allResourceMap, Long parentId) {
        List<SysResourceVo> list  = new ArrayList<>(10);
        for(SysResource sysResource :  allResourceList ){
            if(parentId.equals(sysResource.getParentId())){
                SysResourceVo sysResourceVo = new SysResourceVo();
                BeanUtils.copyProperties(sysResourceVo,sysResource);
                list.add(sysResourceVo);
                List<SysResourceVo> childrenList = toResourceVo(allResourceList, allResourceMap, sysResource.getResourceId());
                if(childrenList.size() > 0 ){
                    sysResourceVo.setChildren(childrenList);
                }
            }
        }

        Collections.sort(list, new Comparator<SysResourceVo>() {
            @Override
            public int compare(SysResourceVo o1, SysResourceVo o2) {
                if(o1.getOrderNo()== null || o2.getOrderNo() == null ){
                    logger.warn("detect orderNo is null on SysResource[{}] or SysResource[{}]", o1.getResourceId(),o2.getResourceId() );
                }
                return o1.getOrderNo() - o2.getOrderNo() ;
            }
        });

        return list;
    }


}